package org.gwtde.client.views;

import net.mygwt.ui.client.Events;
import net.mygwt.ui.client.Registry;
import net.mygwt.ui.client.Style;
import net.mygwt.ui.client.data.Model;
import net.mygwt.ui.client.event.BaseEvent;
import net.mygwt.ui.client.event.Listener;
import net.mygwt.ui.client.mvc.AppEvent;
import net.mygwt.ui.client.mvc.Controller;
import net.mygwt.ui.client.mvc.Dispatcher;
import net.mygwt.ui.client.mvc.View;
import net.mygwt.ui.client.util.Rectangle;
import net.mygwt.ui.client.viewer.ISelectionChangedListener;
import net.mygwt.ui.client.viewer.ModelLabelProvider;
import net.mygwt.ui.client.viewer.ModelTreeContentProvider;
import net.mygwt.ui.client.viewer.SelectionChangedEvent;
import net.mygwt.ui.client.viewer.TreeViewer;
import net.mygwt.ui.client.widget.DesktopShell;
import net.mygwt.ui.client.widget.ExpandBar;
import net.mygwt.ui.client.widget.ExpandItem;
import net.mygwt.ui.client.widget.Shell;
import net.mygwt.ui.client.widget.ShellManager;
import net.mygwt.ui.client.widget.ToolButton;
import net.mygwt.ui.client.widget.WidgetContainer;
import net.mygwt.ui.client.widget.layout.FillLayout;
import net.mygwt.ui.client.widget.tree.Tree;

import org.gwtde.client.Desktop;
import org.gwtde.client.DesktopEvents;
import org.gwtde.client.model.AppLink;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;

public class DockView extends View {

	private Shell mShell;
	private ExpandBar mExpandBar;
	private Tree mTree;
	private TreeViewer mTreeViewer;
	private Model mModel;
	private ToolButton mPinBtn;
	private boolean mPinned = false;
	private Rectangle mOldBounds = null;

	private Listener mCloseListener = new Listener() {
		public void handleEvent(BaseEvent be) {
			mShell = null;
			unpin();
		}
	};
	private Listener mUnpinListener = new Listener() {
		public void handleEvent(BaseEvent be) {
			unpin();
		}
	};

	public DockView(Controller pController, Model pModel) {
		super(pController);
		mModel = pModel;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.mygwt.ui.client.mvc.View#initialize()
	 */
	protected void initialize() {
		Registry.register("dock", this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.mygwt.ui.client.mvc.View#handleEvent(net.mygwt.ui.client.mvc.AppEvent)
	 */
	protected void handleEvent(AppEvent pEvent) {
		switch (pEvent.type) {
		case DesktopEvents.Init:
		case DesktopEvents.DockActivate:
			if (mShell == null) {
				activateHandler();
			} else {
				ShellManager.get().setActive(mShell);
			}
			break;
		case DesktopEvents.DockNavApps:
			break;
		}
	}

	private void activateHandler() {
		createShell();
		createExpandBar();

		WidgetContainer c = mShell.getContent();
		c.setLayout(new FillLayout());
		c.add(mExpandBar);
		c.layout();

		createAppsFolder();
	}

	public boolean isPinned() {
		return mPinned;
	}

	private void pin() {
		mPinned = true;
		mPinBtn.changeStyle("my-tool-pin");
		Dispatcher.forwardEvent(DesktopEvents.DockPinned);
	}

	private void unpin() {
		mPinned = false;
		mPinBtn.changeStyle("my-tool-unpin");
		Dispatcher.forwardEvent(DesktopEvents.DockUnPinned);
	}

	private void createShell() {
		final Rectangle desktopBounds = Desktop.getBounds();

		mShell = new DesktopShell();
		mShell.setSize(200, (int) (Desktop.getClientHeight() / 1.5));
		mShell.setMinimumSize(200, (int) (Desktop.getClientHeight() / 1.5));

		// mShell.animate = true;

		mShell.setIconStyle("icon-gear");
		mShell.setText("GWT Desktop Dock");

		mShell.getContent().addStyleName("gwtde-dock-content");

		mPinBtn = new ToolButton("my-tool-unpin");
		mPinBtn.setTitle("Reset GWT Desktop dock");
		mPinBtn.addListener(Events.Click, new Listener() {
			public void handleEvent(BaseEvent be) {
				if (mPinned) {
					if (mOldBounds != null) {
						mShell.setBounds(mOldBounds);
						mOldBounds = null;
					}
					unpin();
				} else {
					mOldBounds = mShell.getBounds();
					if ((mOldBounds.x + mOldBounds.width / 2) <= (Desktop
							.getClientWidth() / 2)) {
						Rectangle r = new Rectangle(desktopBounds.x,
								desktopBounds.y, 200, Desktop.getClientHeight());
						mShell.setBounds(r);
					} else {
						Rectangle r = new Rectangle(desktopBounds.x
								+ desktopBounds.width - 200, desktopBounds.y,
								200, Desktop.getClientHeight());
						mShell.setBounds(r);
					}
					pin();
				}
			}
		});
		mShell.getHeader().addWidget(mPinBtn);

		mShell.addListener(Events.Close, mCloseListener);
		mShell.addListener(Events.Resize, mUnpinListener);
		mShell.getDraggable().container = Desktop.getContainer();
		mShell.getDraggable().addListener(Events.DragEnd, mUnpinListener);

		mShell.open();
		mShell.setLocation(desktopBounds.x + 0, desktopBounds.y + 0);
	}

	private void createExpandBar() {
		mExpandBar = new ExpandBar(Style.SINGLE | Style.HEADER);
		mExpandBar.setBorders(false);
		// expandBar.headerHeight = 28;

		ExpandItem appsItem = new ExpandItem();
		appsItem.setText("Applications");
		appsItem.addListener(Events.Expand, new Listener() {
			public void handleEvent(BaseEvent be) {
				Dispatcher.forwardEvent(DesktopEvents.DockNavApps);
			}
		});
		appsItem.setExpanded(true);
		mExpandBar.add(appsItem);

		Registry.register("dock-apps-item", appsItem);
	}

	private void createAppsFolder() {
		mTree = new Tree(Style.SINGLE);
		mTree.setItemImageStyle("icon-shell");

		mTreeViewer = new TreeViewer(mTree);
		mTreeViewer.setLabelProvider(new ModelLabelProvider());
		mTreeViewer.setContentProvider(new ModelTreeContentProvider());

		mTreeViewer.addSelectionListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				Model m = (Model) event.getSelection().getFirstElement();
				if (m instanceof AppLink) {
					AppLink link = (AppLink) m;
					Dispatcher.forwardEvent(new AppEvent(
							DesktopEvents.ShellOpenURL, link));
				}
			}
		});

		mTreeViewer.setInput(mModel);

		ExpandItem item = (ExpandItem) Registry.get("dock-apps-item");
		WidgetContainer c = item.getContainer();
		c.setScrollEnabled(true);
		c.add(mTree);
	}

	public Rectangle getBounds() {
		return mShell != null ? mShell.getBounds() : null;
	}
}
